package com.tiny.work.plane;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.tiny.work.plane.factory.AutoModelFactory;
import com.tiny.work.plane.factory.IFactory;
import com.tiny.work.plane.factory.IrritableFactory;
import com.tiny.work.plane.factory.NormalFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FlightPlane {

    private static final Logger LOGGER = LoggerFactory.getLogger(FlightPlane.class);

    public static List<List<ArrangePilot>> result = Lists.newArrayList();

    public static <T extends Pilot> void swap(T[] arr, int a, int b) {
        T t = arr[a];
        arr[a] = arr[b];
        arr[b] = t;
    }

    public static Pilot initMale() {
        IFactory normalFactory = new NormalFactory();
        IFactory irritableFactory = new IrritableFactory();
        IModel normalFactoryModel = normalFactory.createModel(new BigDecimal("0.00001"), new BigDecimal("0.00125"));
        IModel irritableFactoryModel = irritableFactory.createModel(
            new BigDecimal("0.00001"), new BigDecimal("0.00125"),
            new BigDecimal("0.00001"), new BigDecimal("0.0013")
        );
        return new Pilot(
            Lists.newArrayList(normalFactoryModel, irritableFactoryModel),
            Lists.newArrayList(new OvertimeOrderRuler(11))
        );
    }

    public static Pilot initFeMale() {

        IFactory autoFactory = new AutoModelFactory();
        IFactory normalFactory = new NormalFactory();
        IModel normalFactoryModel = normalFactory.createModel(new BigDecimal("0.000008"), new BigDecimal("0.0016"));
        IModel autoFactoryModel = autoFactory.createModel(new BigDecimal("0.000015"), new BigDecimal("0.0017"));
        return new Pilot(true, DateUtils.toDate("2019-01-01 00:00:00"),
            Lists.newArrayList(normalFactoryModel, autoFactoryModel),
            Lists.newArrayList(new SpecialTimeOrderRuler())
        );
    }


    public static void arrange(ArrangePilot[] pilots, int index) {
        if (index >= pilots.length) {
//            LOGGER.info("{}", JSON.toJSONString(pilots));
            List<ArrangePilot> arrangePilots = Lists.newArrayList();
            for (ArrangePilot arrangePilot : pilots) {
                try {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    ObjectOutputStream oos = new ObjectOutputStream(bos);
                    oos.writeObject(arrangePilot);
                    oos.flush();
                    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
                    ArrangePilot stu2 = (ArrangePilot) ois.readObject();
                    arrangePilots.add(stu2);
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
            result.add(arrangePilots);
            return;
        }
        for (int i = index; i < pilots.length; i++) {
            ArrangePilot arrangePilot = pilots[i];
            Date curTime = DateUtils.addDay(DateUtils.toDate("2019-01-01 00:00:00"), i);
            arrangePilot.curTime = curTime;
            Pilot pilot = initMale();
            pilot.setFlightDays(getHistoryArrange(pilots, index, pilot));
            arrangePilot.pilot = pilot;
            if (!arrangePilot.canOrder()) {
                arrangePilot.pilot = initFeMale();
                pilot.setFlightDays(getHistoryArrange(pilots, index, pilot));
                if (!arrangePilot.canOrder()) {
                    arrangePilot.pilot = null;
                    return;
                }
            } else {
                pilots[i] = arrangePilot;
            }
            arrange(pilots, i + 1);
            arrangePilot.curTime = curTime;
            pilot = initFeMale();
            pilot.setFlightDays(getHistoryArrange(pilots, index, pilot));
            arrangePilot.pilot = pilot;
            if (!arrangePilot.canOrder()) {
                pilot = initMale();
                pilot.setFlightDays(getHistoryArrange(pilots, index, pilot));
                if (!arrangePilot.canOrder()) {
                    arrangePilot.pilot = null;
                    return;
                } else {
                    pilots[i].pilot = pilot;
                }
            } else {
                pilots[i].pilot = pilot;
            }
//            if (index <= pilots.length - 1) {
//            LOGGER.info("{}", JSON.toJSONString(pilots));
//            result.add(Lists.newArrayList(pilots));
//                return;
//            }
        }
    }

    private static int getHistoryArrange(ArrangePilot[] pilots, int index, Pilot pilot) {
        int result = 0;
        for (int i = 0; i < index; i++) {
            if (pilots[i].pilot != null && pilots[i].pilot.isFemale() == pilot.isFemale()) {
                result++;
            }
        }
        return result;
    }

    public static void main(String[] args) {
        ArrangePilot[] pilots = new ArrangePilot[6];
        for (int i = 0; i < pilots.length; i++) {
            pilots[i] = new ArrangePilot();
        }
        arrange(pilots, 0);
        LOGGER.info("result:{}", result.size());
        Random random = new Random(100);
        for (List<ArrangePilot> arrangePilots : result) {
            for (ArrangePilot pilot : arrangePilots) {
                PlaneResult planeResult = pilot.pilot
                    .fligthResult(Constants.JOURNEY_PER_DAY, new BigDecimal(random.nextInt(60) + 60), pilot);
                LOGGER.info("{}", JSON.toJSONString(planeResult));
            }
        }
    }
}
